// 获取指定圆边界上的点，需要指定圆心和半径m
// 依赖geodesy （npm install geodesy）
import geodesy from "geodesy";

var NORTH_POLE = new geodesy.LatLonEllipsoidal(90, -180);
var SOUTH_POLE = new geodesy.LatLonEllipsoidal(-90, 180);
var LONGITUDE_DELTA_WRAP_CUTOFF = 90;
var CIRCLE_SEGMENTS = 720;
var MAX_RADIUS_METERS = 10 * 1000 * 1000; // Max 10,000 km radius to prevent wrap-around inversion artifacts

export default {
  initialize(latlng, radius) {
    this._latlng = L.latLng(latlng);
    this._mRadius = Math.min(MAX_RADIUS_METERS, radius);
    return this._computeShape(this._latlng, this._mRadius);
  },

  setLatLng(latlng) {
    this._latlng = L.latLng(latlng);
    var shape = this._computeShape(this._latlng, this._mRadius);
    return this.setLatLngs(shape);
  },

  getLatLng() {
    return this._latlng;
  },

  setRadius(radius) {
    this._mRadius = Math.min(MAX_RADIUS_METERS, radius);
    var shape = this._computeShape(this._latlng, this._mRadius);
    return this.setLatLngs(shape);
  },

  getRadius() {
    return this._mRadius;
  },

  /*
      Compute multipolygon shape that includes the points on a globe
      having a distance to "center" less than "radius".
  
      Do this by determining the lat/lon of each bearing around
      the compass at that distance.
    */
  _computeShape(center, radius) {
    var center = new geodesy.LatLonEllipsoidal(center.lat, center.lng);
    var coords = [];
    for (var i = 0; i < CIRCLE_SEGMENTS; i++) {
      var bearing = (i * 360.000000) / CIRCLE_SEGMENTS;
      coords.push(center.destinationPoint(radius, bearing));
    }
    return this._correctProjectionWrapAround(coords, center, this._radius);
  },

  _correctProjectionWrapAround(coords, center, radius) {
    var multipolygon = [[]];
    var part = 0;

    for (var i = 1; i <= coords.length; i++) {
      var c0 = coords[i - 1];
      var c1 = i === coords.length ? coords[0] : coords[i];

      // correct the shape if we cross the anti-meridian or a pole.
      var deltaLon = c1.lon - c0.lon;
      if (deltaLon > LONGITUDE_DELTA_WRAP_CUTOFF) {
        if (center.distanceTo(NORTH_POLE) > radius) {
          // anti-meridian case
          if (part === 0) {
            multipolygon[part].push({ lat: c0.lat, lon: -180 });
            multipolygon.push([]);
            part = 1;
            multipolygon[part].push({ lat: c1.lat, lon: 180 });
          } else {
            multipolygon[part].push({ lat: c0.lat, lon: -180 });
            part = 0;
            multipolygon[part].push({ lat: c1.lat, lon: 180 });
          }
        } else {
          // north pole case
          multipolygon[part].push({ lat: c0.lat, lon: -180 });
          multipolygon[part].push({ lat: 90, lon: -180 });
          multipolygon[part].push({ lat: 90, lon: 180 });
          multipolygon[part].push({ lat: c1.lat, lon: 180 });
        }
      }

      if (deltaLon < -LONGITUDE_DELTA_WRAP_CUTOFF) {
        if (center.distanceTo(SOUTH_POLE) > radius) {
          // anti-meridian case
          if (part === 0) {
            multipolygon[part].push({ lat: c0.lat, lon: 180 });
            multipolygon.push([]);
            part = 1;
            multipolygon[part].push({ lat: c1.lat, lon: -180 });
          } else {
            multipolygon[part].push({ lat: c0.lat, lon: 180 });
            part = 0;
            multipolygon[part].push({ lat: c1.lat, lon: -180 });
          }
        } else {
          // south pole case
          multipolygon[part].push({ lat: c0.lat, lon: 180 });
          multipolygon[part].push({ lat: -90, lon: 180 });
          multipolygon[part].push({ lat: -90, lon: -180 });
          multipolygon[part].push({ lat: c1.lat, lon: -180 });
        }
      }

      // finally add the computed coordinate
      multipolygon[part].push(c1);
    }

    return multipolygon;
  },
  /**
   * 经纬度转墨卡托
   * @param poi 经纬度
   * @returns {{}}
   * @private
   */
  _getMercator(poi) {
    //[114.32894, 30.585748]
    var mercator = {};
    var earthRad = 6378137.0;
    // console.log("mercator-poi",poi);
    mercator.x = ((poi.lng * Math.PI) / 180) * earthRad;
    var a = (poi.lat * Math.PI) / 180;
    mercator.y =
      (earthRad / 2) * Math.log((1.0 + Math.sin(a)) / (1.0 - Math.sin(a)));
    // console.log("mercator",mercator);
    return mercator; //[12727039.383734727, 3579066.6894065146]
  },
  /**
   * 墨卡托转经纬度
   * @param poi 墨卡托
   * @returns {{}}
   * @private
   */
  _getLngLat(poi) {
    var lnglat = {};
    lnglat.lng = (poi.x / 20037508.34) * 180;
    var mmy = (poi.y / 20037508.34) * 180;
    lnglat.lat =
      (180 / Math.PI) *
      (2 * Math.atan(Math.exp((mmy * Math.PI) / 180)) - Math.PI / 2);
    return lnglat;
  },
  // pois 为_correctProjectionWrapAround 的返回值
  _getMercators(pois) {
    debugger;
    let mercators = [];
      for (let i = 0; i < pois[0].length; i++) {
      let poi = pois[0][i];
      //[[114.32894, 30.585748]]
      var mercator = {};
      var earthRad = 6378137.0;
      // console.log("mercator-poi",poi);
      mercator.lat = ((poi.lon * Math.PI) / 180) * earthRad;
      var a = (poi.lat * Math.PI) / 180;
      mercator.lng =
        (earthRad / 2) * Math.log((1.0 + Math.sin(a)) / (1.0 - Math.sin(a)));
      mercators.push(mercator);
    }
    return mercators;
  },
  // pois 为_correctProjectionWrapAround 的返回值[[{},{},{}]
  _getLngLat(pois) {
    let lnglats = [];
      for (let i = 0; i < pois[0].length; i++) {
      let poi = pois[0][i];
      var lnglat = {};
      lnglat.lng = (poi.lat / 20037508.34) * 180;
      var mmy = (poi.lon / 20037508.34) * 180;
      lnglat.lat =
        (180 / Math.PI) *
        (2 * Math.atan(Math.exp((mmy * Math.PI) / 180)) - Math.PI / 2);
      lnglats.push(latLng);
    }
    return lnglats;
  }
};
